package main

import (
	"errors"
	"flag"
	"fmt"
	"html/template"
	"log"
	"os"
	"path/filepath"
	"strings"
)

var (
	dir    = flag.String("d", "../..", "请输入路径")
	app    = flag.String("a", "test", "请输入所属服务")
	models = flag.String("m", "User,Menu,Role,Dept", "请输入Model模型")
)

type Generator struct {
	Model string
	App   string
	Name  string
}

// tpler
func (g Generator) CreateFile(tpler, gofile string) (string, error) {
	filename := filepath.Join(*dir, "api", g.App, gofile)
	_, err := os.Stat(filename)
	if err == nil {
		return filename, errors.New("has created")
	}
	os.MkdirAll(filepath.Dir(filename), os.ModePerm)
	file, err := os.Create(filename)
	if err != nil {
		return filename, err
	}
	tpl, _ := template.ParseFiles(fmt.Sprintf("%s/templete/%s.tpl", *dir, tpler))
	if tpler == "model" {
		g.App = strings.Title(g.App)
	}
	tpl.Execute(file, g)
	file.Close()
	return filename, nil
}

func (g Generator) ModifyFile(tpler, gofile string, handler func(b []byte) string) {
	filename, err := g.CreateFile(tpler, gofile)
	if err == nil {
		return
	}
	file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0666)
	if err != nil {
		log.Fatalln(err)
	}
	b, _ := os.ReadFile(filename)
	tplstr := handler(b)
	file.WriteString(tplstr)
	file.Close()
}

func main() {
	flag.Parse()
	arr := strings.Split(*models, ",")
	for _, v := range arr {
		g := &Generator{App: *app}
		g.Model = v
		g.Name = strings.ToLower(v)
		g.CreateFile("controller", "controller/"+g.Name+".go")
		g.CreateFile("model", "model/"+g.Name+".go")
		g.ModifyFile("dto", "dto/where.go", func(b []byte) string {
			s1 := "switch v.(type) {\n"
			s2 := s1 + "\tcase *model.%s:\n"
			return strings.ReplaceAll(string(b), s1, fmt.Sprintf(s2, g.Model))
		})
		g.ModifyFile("main", "main.go", func(b []byte) string {
			s1 := "orm.RegisterModel(\n"
			s2 := fmt.Sprintf("\t\t&model.%s{},\n", g.Model)
			tplstr := strings.ReplaceAll(string(b), s1, s1+s2)
			r1 := "func(r *gin.RouterGroup) {\n"
			r2 := fmt.Sprintf("\t\tcontroller.%s{}.Routers(r.Group(\"/%s\"))\n", g.Model, g.Name)
			return strings.ReplaceAll(tplstr, r1, r1+r2)
		})
	}
}
